package cxm.proj.xtalk.smack;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import cxm.lib.util.MyApplication;
import cxm.lib.util.MyLog;
import cxm.proj.xtalk.CallActivity;
import cxm.proj.xtalk.smack.CallManager.CallManagerNotify;

// upload ftp file with background servcie
@SuppressLint("HandlerLeak")
public class OnlineService extends Service {
	private Looper mServiceLooper;
	private ServiceHandler mServiceHandler;
	private boolean needRelogin = false;

	// Handler that receives messages from the thread
	private final class ServiceHandler extends Handler
			implements CallManagerNotify {
		public ServiceHandler(Looper looper) {
			super(looper);
		}
		
		// true for login, false for fail login
		private boolean checkLogin() {
			// check user login state
			if (UserManager.getInstance().hasUser() &&
					UserManager.getInstance().getUser().isLogin())
				return true;
			MyLog.Log(MyLog.Level.Warning, "Service start before User Login, now try to login");
			
			// get settings
			SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OnlineService.this);
			// prepare connect manager
			do {
				if (!ConnectManager.getInstance().hasConnector()) {
					// set ConnectManager
					String serverip = prefs.getString("prefs_serverip", "");
					String servername = prefs.getString("prefs_servername", "");
					if (serverip.length() == 0 || servername.length() == 0) {
						MyLog.Log(MyLog.Level.Error, "Cannot get server info, abandon login");
						break;
					}
					ConnectManager.getInstance().createConnector(serverip, servername);
				}
				// login
				String user = prefs.getString("user", "");
				String pass = prefs.getString("pass", "");
				if (user.length() == 0 || pass.length() == 0) {
					MyLog.Log(MyLog.Level.Error, "Cannot get user or pass");
					break;
				}
				UserManager.getInstance().setLoginAccount(user, pass);
				try {
					UserManager.getInstance().login(null, null);
					return true;
				} catch (Exception e) {
					MyLog.Log(MyLog.Level.Error, "Cannot login: " + e);
					break;
				}
			} while(false);
			
			// reverse state
			ConnectManager.Release();
			UserManager.Release();
			
			return false;
		}

		@Override
		public void handleMessage(Message msg) {
			// check is login first
			this.checkLogin();

			// register notify for listen incoming call
			CallManager cm = CallManager.getInstance();
			try {
				cm.startListen(this);
			} catch (Exception e) {
				MyLog.Log(MyLog.Level.Error, "Cannot listen call: " + e);
				return;
			}
			
			// notify for reconnection

			// loop forever to listening incoming call
			boolean isRun = true;
			while (isRun) {
				// check relogin
				if (OnlineService.this.needRelogin) {
					MyLog.Log(MyLog.Level.Info, "Relogin cause needing");
					if (this.checkLogin()) // undo state when login success
						OnlineService.this.needRelogin = false;
				}

				// sleep for a while
				try {
					Thread.sleep(1000, 0);
				} catch (Exception e) {
					MyLog.Log(MyLog.Level.Error, "Cannot sleep: " + e);
				}
				
				// TODO stop service
			}

			// remove notify
			cm.stopListen();
		}

		@Override
		public void onCall(Call call) {
			// start call intent
			Intent intent = new Intent(MyApplication.context, CallActivity.class);
			intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			startActivity(intent);
		}
	}
	
	private BroadcastReceiver messageReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			MyLog.Log(MyLog.Level.Info, "Receiver intent " + intent.getAction());
			// Log out, go to login activity
			UserManager.Release();
			
			// set relogin
			OnlineService.this.needRelogin = true;
		}
	};
	
	@Override
	public void onCreate() {
		MyLog.Log(MyLog.Level.Info, "Starting listening service");
		// Start up the thread running the service.  Note that we create a
		// separate thread because the service normally runs in the process's
		// main thread, which we don't want to block.  We also make it
		// background priority so CPU-intensive work will not disrupt our UI.
		HandlerThread thread = new HandlerThread("ServiceStartArguments");
		thread.start();

		// Get the HandlerThread's Looper and use it for our Handler 
		mServiceLooper = thread.getLooper();
		mServiceHandler = new ServiceHandler(mServiceLooper);
		
		// register connection broadcast
		LocalBroadcastManager.getInstance(this).registerReceiver(this.messageReceiver,
				new IntentFilter(Connector.CONNECTION_EVENT));
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// For each start request, send a message to start a job and deliver the
		// start ID so we know which request we're stopping when we finish the job
		Message msg = mServiceHandler.obtainMessage();
		msg.arg1 = startId;
		mServiceHandler.sendMessage(msg);

		// If we get killed, after returning from here, restart
		return START_STICKY;
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null; }

	@Override
	public void onDestroy() {
		MyLog.Log(MyLog.Level.Info, "service destroy");
		
		LocalBroadcastManager.getInstance(this).unregisterReceiver(
				this.messageReceiver);
	}
}
